package data

import (
	"context"
	"fmt"
	"time"

	"rosesbff/internal/conf"

	registry "github.com/go-kratos/kratos/contrib/registry/nacos/v2"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware"
	mmd "github.com/go-kratos/kratos/v2/middleware/metadata"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	transgrpc "github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/model"
	"github.com/nacos-group/nacos-sdk-go/vo"
	"google.golang.org/grpc"
)

type GRPCClient struct {
	news    *grpc.ClientConn
	dtm     *grpc.ClientConn
	account *grpc.ClientConn
	common  *grpc.ClientConn
	article *grpc.ClientConn
}
type NacosServiceDiscovery struct {
	client naming_client.INamingClient
}

func NewNacosServiceDiscovery(client naming_client.INamingClient) *NacosServiceDiscovery {
	return &NacosServiceDiscovery{
		client: client,
	}
}

func (n *NacosServiceDiscovery) DiscoverService(serviceName, groupName string) ([]model.Instance, error) {
	instances, err := n.client.SelectInstances(vo.SelectInstancesParam{
		ServiceName: serviceName,
		GroupName:   groupName,
		HealthyOnly: true, // 只获取健康实例
	})
	if err != nil {
		return nil, fmt.Errorf("failed to discover service %s in group %s: %w", serviceName, groupName, err)
	}
	return instances, nil
}

func NewGRPCClient(c *conf.Bootstrap, logger log.Logger) (*GRPCClient, error) {
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(c.Server.Registry.Addr, c.Server.Registry.Port),
	}

	cc := &constant.ClientConfig{
		NamespaceId:         c.Server.Registry.Namespace, // namespace id
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "logs",
		CacheDir:            "nacos/cache",
		// RotateTime:          "1h",
		// MaxAge:              3,
		LogLevel: c.Server.Registry.Loglevel,
	}

	// a more graceful way to create naming client
	cli, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  cc,
			ServerConfigs: sc,
		},
	)
	if err != nil {
		return nil, err
	}

	// conn, err := NewRpcConn(cli, "demoserveice.grpc", "news")
	// if err != nil {
	// 	log.Error(err.Error())
	// }
	// dtm, err := NewRpcConn(cli, "dtmservice.grpc", "dtm")

	common, err := NewRpcConn(cli, "roses.grpc", "news")
	if err != nil {
		return nil, err
	}

	account, err := NewRpcConn(cli, "roses.grpc", "news")
	if err != nil {
		return nil, err
	}

	article, err := NewRpcConn(cli, "roses.grpc", "news")
	if err != nil {
		return nil, err
	}

	d := &GRPCClient{
		// news:   conn,
		// dtm:    dtm,
		common:  common,
		account: account,
		article: article,
	}

	return d, nil
}

func NewRpcConn(cli naming_client.INamingClient, servicename string, group string) (*grpc.ClientConn, error) {
	bb := NewNacosServiceDiscovery(cli)
	instances, err := bb.DiscoverService(servicename, group)
	if err != nil {
		return nil, err
	}
	if len(instances) == 0 {
		return nil, fmt.Errorf("no instance found for service %s in group %s", servicename, group)
	}
	instance := instances[0]
	addr := fmt.Sprintf("%s:%d", instance.Ip, instance.Port)
	conn, err := transgrpc.DialInsecure(
		context.Background(),
		// transgrpc.WithEndpoint("127.0.0.1:9000"),
		transgrpc.WithMiddleware(
			middleware.Chain(
				recovery.Recovery(),
				mmd.Client(),
			),
			tracing.Client(),
		),
		// nacos 发现服务

		transgrpc.WithEndpoint(addr),
		transgrpc.WithDiscovery(registry.New(cli, registry.WithGroup(group))),
		// transgrpc.WithDiscovery(registry.New(cli)),
		transgrpc.WithTimeout(2*time.Second),
	)
	if err != nil {
		return nil, err
	}
	return conn, nil
}

// 封装nacos服务发现
